package com.andy.app_core.net.databus;

import java.lang.reflect.Method;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * @version V1.0
 * @描述: 数据总线
 * @auth: Created by AN .
 * @time: 2020/3/27 01:41
 * @des
 */
public class RxBus {
    private Set<Object> subscribes;

    /**
     * 注册
     */
    public synchronized void register(Object subscriber){
        subscribes.add(subscriber);
    }
    public synchronized void unRegister(Object subscriber){
        subscribes.remove(subscriber);
    }

    private static volatile RxBus instance;
    private RxBus(){
        subscribes=new CopyOnWriteArraySet<>();//读写分离的集合,自带线程安全的
    }
    public synchronized static RxBus getInstance(){
        if(instance ==null){
            synchronized (RxBus.class){
                if (instance == null){
                    instance =new RxBus();
                }
            }
        }
        return instance;
    }

    public void chainProcess(Function function){
        Observable.just("")
                .subscribeOn(Schedulers.io())
                .map(function)//在此处进行网络访问
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer() {
                    @Override
                    public void accept(Object data) throws Exception {
                        //data会传递到总线上
                        if(data == null){
                            return;
                        }else{
                            sendData(data);
                        }
                    }
                });
    }

    public  void sendData(Object data) {
        for (Object subscriber :subscribes  ) {
            //扫描注解,把数据发送到注册的对象标记方法的位置
            callMethodByAnnotation(subscriber,data);
        }
    }

    private void callMethodByAnnotation(Object targe,Object data){
        //1.得到presenter中所有的方法
        Method[] methods = targe.getClass().getDeclaredMethods();
        //遍历方法名,找到有RegisterRxBus的
        for (int i = 0; i < methods.length; i++) {
            try {
            if(methods[i].getAnnotation(RegisterRxBus.class)!=null){
                Class paramType=methods[i].getParameterTypes()[0];
                //第一个参数类型相同的,执行.吧数据传递上去
                if(data.getClass().getName().equals(paramType.getName())){
                    methods[i].invoke(targe, new Object[]{data});
                }
            }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
